#include <vcl.h>
#include <FileCtrl.hpp>
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <dos.h>
#include <fcntl.h>
#include <sys\stat.h>
#pragma hdrstop

#include <EIC.H>
#include "uFileOp.h" //Pour la fonction EicDirDeleteContenu
#include "Implode.h"
#include "CBackupR.h"
#pragma package(smart_init)

// Messages d'erreur pour BR
////////////////////////////
AnsiString aBRErrMsg[NB_CODES_RET] =
	{
 	"Opération réussie avec succès",            // BR_OK
 	"Action en cours",                          // BR_REDO
 	"Action arrêtée",                           // BR_STOP
	"Processus abandonné",                      // BR_ACTION_CANCELED
	"Mémoire insuffisante",                     // BR_ERR_EXHAUSTED_MEMORY
 	"Répertoire Backup/Restore non trouvé",     // BR_ERR_BR_PATH_NOT_FOUND
 	"Aucun fichier à sauvegarder",              // BR_ERR_NO_SRC_FILE_TO_BACKUP
 	"Erreur d'accès au fichier temporaire",     // BR_ERR_TMP_FILE_ACCESS_IO_ERROR
	"Erreur durant la compression",             // BR_ERR_IMPLODING_FILE
 	"Erreur durant la décompression",           // BR_ERR_EXPLODING_FILE
	"Erreur d'écriture du fichier destination", // BR_ERR_DEST_FILE_WRITE_ERROR
 	"Erreur de lecture du fichier source",      // BR_ERR_SRC_FILE_READ_ERROR
 	"Fichier détruit durant la sauvegarde",     // BR_ERR_SRC_FILE_DELETED_DURING_BACKUP
	"Fichier de sauvegarde corrompu",           // BR_ERR_BR_FILE_CORRUPTED
	"Lecteur invalide",                         // BR_ERR_DRIVE_UNKNOW
	"Disque plein ou protégé en écriture",  		// BR_ERR_DRIVE_PROTECT
	"Disque plein"								// BR_ERR_DRIVE_OUTOFSPACE
	};



//---------------------------------------------------------------------------
// ValidCtrCheck est utilisé pour être sûr que les composants créés ne
// contiennent aucune fonction virtuelle pure.
//

static inline void ValidCtrCheck(CBackupRestore *)
	{
	new CBackupRestore(NULL);
	}




/////////////////////////
/////////////////////////
////
////   Compression
////
/////////////////////////
/////////////////////////
unsigned int _ReadFile_(char *pBuffer, unsigned int *nSize, void *pParams)
	{
	TWriteParams *pParm = (TWriteParams *)pParams;
	return pParm->pRStream->Read(pBuffer, *nSize);
	}

void _WriteFile_(char *pBuffer, unsigned int *nSize, void *pParams)
	{
	TWriteParams *pParm  = (TWriteParams *)pParams;
	pParm->nImplodeSize += pParm->pWStream->Write(pBuffer, *nSize);
	}




////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
__fastcall CBackupRestore::CBackupRestore(TComponent* Owner)
	: TComponent(Owner)
	{
	FBackup 				  = NULL;
	FCmpDst				  = NULL;
	FCmpSrc 				  = NULL;
	ListPathToBackup	  = NULL;
	bDeleteFilesBeforeBackup = false;
	FAutoEvents			  = FAutoEvents << eBRBeginBackup 	    << eBRBeginRestore 	    << eBRInsertFloppy 	<< eBRPercents;
	FAutoEvents			  = FAutoEvents << eBRGetPatternToBackup  << eBRRestorePattern 	<< eBRError 		<< eBRHardError 	<< eBREnd;
	}

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::SetDirectory(const AnsiString &aNewDirectory )
	{
	FDirectory = aNewDirectory;

	if( !FDirectory.IsEmpty())
		{
		if( FDirectory[FDirectory.Length()] != '\\' )
			FDirectory += "\\";
		}
	}




////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::SetBRDirectory(const AnsiString &aNewDirectory )
	{
	FBRDirectory = aNewDirectory;

	if( !FBRDirectory.IsEmpty())
		{
		if( FBRDirectory[FBRDirectory.Length()] != '\\' )
			FBRDirectory += "\\";
		}

	aBRFilePath = FBRDirectory;
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::SetBRFileName(const AnsiString &aNewFileName )
	{
	FBRFileName = aNewFileName;
	aBRFileName	= FBRFileName;
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::SetAutoEvents( TListEventsBR NewAutoEvents )
	{
	FAutoEvents = NewAutoEvents;
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::Backup()
	{
	unsigned short 	uhTmp;
	BR_CODE 		eRetCode;
	AnsiString 		aTemp;
	unsigned short 	uhUserDataLen = 0;
	unsigned short 	uhHighNumVers;
	unsigned short 	uhLowNumVers;
	bool 			bForCancel;
	AnsiString 		aTmpFile;
	char			szBuff[MAXPATH] = "";
   DWORD           AdrIOBuffTemp;
   TSearchRec OptionsRech;

	try
		{
		//if( !DirectoryExists(Directory))
		if( access( Directory.c_str(), 0 ) == -1 && FAutoEvents.Contains(eBRGetPatternToBackup))
			{
			eRetCode = BR_ERR_BR_PATH_NOT_FOUND;
			if( OnError && !FAutoEvents.Contains(eBRError))
				OnError( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );
			else if( FAutoEvents.Contains(eBRError))
				OnOwnError( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );
			return( eRetCode );
			}

//Anthony, le 22/03/02
//		::GetWindowsDirectory( szBuff, MAXPATH );
      ::GetTempPath(MAXPATH, szBuff);
		aTmpFile = AnsiString(szBuff) + "BR.TMP";

		// Initialisation
		/////////////////
		bForBackup  = true;

		ListPathToBackup = new TStringList();

		// Vérification du fichier à sauvegarder
		if(( eRetCode = BRBegin( BRDirectory, BRFileName )) != BR_OK )
			{
			// Erreur d'initialisation pour la restauration
			if( OnError && !FAutoEvents.Contains(eBRError))
				OnError( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );
			else if( FAutoEvents.Contains(eBRError))
				OnOwnError( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );

			return( eRetCode );
			}

		// Obtention des SubDirectories
		///////////////////////////////
		if( bForBackup && FAutoEvents.Contains(eBRGetPatternToBackup))
			{
			lAllFilesBR 				= 0;
			IemIndexListPathToBackup 	= 0;
			ListPathToBackup->Clear();
			if( FSubDirectory )
				GetSubDirectories( Directory );
			else
				ListPathToBackup->Add(Directory);
			}

		// Création du descripteur de sauvegarde
		////////////////////////////////////////
		brHeader.Tag = BR_HEADER_TAG;
		time( &brHeader.tiBackup );

		// Notification à l'appelant
		if( OnBeginBackup )
            {
		      OnBeginBackup(this, BR_IO_BUFSIZE - ( 1024 + 4 ), uhUserDataLen, AdrIOBuffTemp, uhHighNumVers, uhLowNumVers );
            if( uhUserDataLen )
                memcpy( IOBuffer, (LPVOID)AdrIOBuffTemp, uhUserDataLen);
            }

		if( FAutoEvents.Contains(eBRPercents))
			{
			BarProgress = new TBarProgress(0, bForBackup );
			BarProgress->Show();
			}

	   // Sauvegarde de la description utilisateur
	   ///////////////////////////////////////////
	   if(( eRetCode = BackupBuffer( &uhUserDataLen, sizeof( unsigned short))) == BR_OK )
		   eRetCode = BackupBuffer( IOBuffer, uhUserDataLen );

	   // Backup des patterns
	   /////////////////////
	   while( eRetCode == BR_OK)
		   {
		   if( BarProgress )
				BarProgress->PBarPath->Position = 0;

			// Lecture du prochain pattern à sauvegarder
			bForCancel = false;
			if( OnGetPatternToBackup && !FAutoEvents.Contains(eBRGetPatternToBackup))
            {
				OnGetPatternToBackup(this, 1024 + 2, uhUserDataLen, AdrIOBuffTemp, aSrcPathPattern, bForCancel);
            if( uhUserDataLen )
                memcpy( IOBuffer, (LPVOID)AdrIOBuffTemp, uhUserDataLen);
            }
			else
				OnOwnGetPatternToBackup(    this, 1024 + 2, uhUserDataLen, IOBuffer, aSrcPathPattern, bForCancel );

			if( BarProgress )
				{
				BarProgress->LDirectory->Caption = aSrcPathPattern;
				BarProgress->LDirectory->Refresh();
				}

			if( bForCancel )
				{
				// Plus de pattern à sauvegarder
				break;
				}


			// Backup du pattern
			////////////////////
			aTemp = MakeFullFile( aSrcPathPattern, "*.*" );

         // Il y a au moins 1 fichier à sauvegarder dans ce pattern
			if(FindFirst( aTemp.c_str(), faReadOnly | faHidden | faSysFile | faArchive, OptionsRech) == 0)
				{
				if(!FCmpDst)
					{
					// Ouverture (en création) du fichier temporaire pour compresser
					try
						{
						FCmpDst 	= new TFileStream( aTmpFile, fmCreate | fmOpenReadWrite | fmShareExclusive );
						}

					catch( Exception &e )
						{
						// Erreur de création/ouverture du fichier temporaire
						eRetCode = BR_ERR_TMP_FILE_ACCESS_IO_ERROR;
						break;
						}
					}

				eRetCode = BackupPattern( uhUserDataLen, IOBuffer );
				}
         FindClose(OptionsRech);
			}

		// Fin du backup
		////////////////
		if( FBackup )
			{
			// Le backup a eu lieu
			// Fermeture du fichier backup
			if( eRetCode == BR_OK)
				{
				// Le backup s'est correctement fait
				uhTmp = 0;
				// Ecriture de l'octet de fin de sauvegarde
				eRetCode = BackupBuffer( &uhTmp, sizeof( unsigned short));
				}

			// Destruction éventuelle du fichier backup
			switch( eRetCode )
				{
				case BR_ERR_ACTION_CANCELED          :
				case BR_ERR_DEST_FILE_WRITE_ERROR    :
				case BR_ERR_TMP_FILE_ACCESS_IO_ERROR :
					{
					aTemp = MakeFullFile( aBRFilePath, aBRFilePath );
					DeleteFile( aTemp );
					}
				break;
				}
			}
		else
			{
			// Le backup n'a pas commencé ou bien a été abandonné
			// au moment de la demande d'une nouvelle disquette.
			if( eRetCode == BR_OK )
				{
				// Aucun pattern n'a été sauvegardé
				eRetCode = BR_ERR_NO_SRC_FILE_TO_BACKUP;
				}
			}

		// Fermeture et destruction du fichier temporaire utilisé pour la compression
		/////////////////////////////////////////////////////////////////////////////
		if( FCmpDst )
			{
			// Un pattern au moins a été sauvegardé
            delete FCmpDst;
            FCmpDst = NULL;
			}

		DeleteFile( aTmpFile );

		if( OnEnd && !FAutoEvents.Contains(eBREnd))
			OnEnd( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );
		else if(FAutoEvents.Contains(eBREnd))
			OnOwnEnd( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );

		if( FAutoEvents.Contains(eBRPercents))
			{
			BarProgress->Close();
			delete BarProgress;
			BarProgress = NULL;
			}

		// Destruction des pointeurs sur fichiers
		/////////////////////////////////////////
		if( FBackup )
            {
			delete FBackup;
            FBackup = NULL;
            }

		if( FCmpDst )
			{
			delete FCmpDst;
			FCmpDst = NULL;
			}

		if( FCmpSrc )
			{
			delete FCmpSrc;
			FCmpSrc = NULL;
			}
		}
	catch( Exception &e )
		{
		ShowMessage( e.Message );
		}
	BREnd();
	return( eRetCode );
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::Restore()
	{
	unsigned short 	uhTmp;
	BR_CODE 		eRetCode;
	AnsiString 		aTemp;
	char 			szTemp[MAXPATH + 1] = "";
	unsigned short 	uhUserDataLen;
	bool 			bForCancel;
	AnsiString		aTmpFile;
	char			szBuff[MAXPATH] = "";

	try
		{
      aSrcPathPattern = "";
      
//Anthony, le 22/03/02
//		::GetWindowsDirectory( szBuff, MAXPATH );
      ::GetTempPath(MAXPATH, szBuff);
		aTmpFile = AnsiString( szBuff ) + "BR.TMP";

		// Initialisation
		/////////////////
		bForBackup   = false;

		// Vérification des paramètres
		//////////////////////////////
		// Vérification du fichier à restaurer
		if(( eRetCode = BRBegin( BRDirectory, BRFileName )) != BR_OK )
			{
			// Erreur d'initialisation pour la restauration
			if( OnError && !FAutoEvents.Contains(eBRError))
				OnError( this, eRetCode, aBRErrMsg[ eRetCode ], bForBackup );
			else if( FAutoEvents.Contains(eBRError))
				OnOwnError( this, eRetCode, aBRErrMsg[ eRetCode ], bForBackup );

			return( eRetCode );
			}

		// Début de la restauration
		///////////////////////////
		// Insertion de la 1ère disquette à restaurer
		// Lecture de la description utilisateur du backup
		if(( eRetCode = BRInsertFloppy()) == BR_OK )
			{
			if(( eRetCode = RestoreBuffer( &uhUserDataLen, sizeof( unsigned short))) == BR_OK )
				{
				if(( eRetCode = RestoreBuffer( IOBuffer, uhUserDataLen )) == BR_OK )
					{
					// Descripteur utilisateur du backup correctement lu
					bForCancel = false;
					if( OnBeginRestore )
						OnBeginRestore( this, uhUserDataLen, IOBuffer, NUM_VERS_1, NUM_VERS_2, bForCancel );

					if( FAutoEvents.Contains(eBRPercents))
						{
						BarProgress = new TBarProgress(/*Applicationtoto*/0, bForBackup );
						BarProgress->Show();
						}

					if( bForCancel )
						{
						// Restauration abandonnée
						eRetCode = BR_ERR_ACTION_CANCELED;
						}
					}
				}
			}

		// Restauration de chaque pattern
		/////////////////////////////////
		while( eRetCode == BR_OK)
			{
			if( BarProgress )
				BarProgress->PBarPath->Position = 0;

			// Lecture du pattern à restaurer
			if(( eRetCode = RestoreBuffer( &uhTmp, sizeof( uhTmp ))) != BR_OK )
				break;

			if( uhTmp == 0 )
				{
				// Dernier pattern restauré
				break;
				}
			else if( uhTmp > ( MAXPATH + 1 ))
				{
				// Taille de chemin incorrecte => Le fichier BR est corrompu
				eRetCode = BR_ERR_BR_FILE_CORRUPTED;
				break;
				}

			if(( eRetCode = RestoreBuffer( szTemp, uhTmp)) == BR_OK )
				{
            //SI szTemp est un chemin complet : "C:\\Test"
            if (szTemp[1]  == ':')
               aSrcPathPattern = szTemp;
            else
               aSrcPathPattern = Directory + szTemp;

				// Restauration du pattern
				eRetCode = RestorePattern( uhUserDataLen, IOBuffer, aTmpFile );
				}
			}

		// Fermeture du fichier backup
		//////////////////////////////
		if( FBackup )
			{
			// La restauration a commencée
			if(( eRetCode == BR_OK ) || ( eRetCode == BR_STOP ))
				{
				// Restauration terminée ou arretée
				delete FBackup;
                FBackup = NULL;
				eRetCode = BR_OK;
				}
			 else
				{
				// Fermeture suite à erreur
                delete FBackup;
                FBackup = NULL;
				}
			}

		// Fermeture et destruction du fichier temporaire
		/////////////////////////////////////////////////
		// Il s'agit du fichier source de décompression
		if( FCmpSrc )
			{
			// Le fichier temporaire a été créé
			delete FCmpSrc;
            FCmpSrc = NULL;
			DeleteFile( aTmpFile );
			eRetCode == BR_OK;
			}

		if( OnEnd && !FAutoEvents.Contains(eBREnd))
			OnEnd( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );
		else if(FAutoEvents.Contains(eBREnd))
			OnOwnEnd( this, eRetCode, aBRErrMsg[eRetCode], bForBackup );

		if( FAutoEvents.Contains(eBRPercents) && BarProgress)
			{
			BarProgress->Close();
			delete BarProgress;
			BarProgress = NULL;
			}

		// Destruction des pointeurs sur fichiers
		/////////////////////////////////////////
		if( FBackup )
            {
            delete FBackup;
            FBackup = NULL;
            }

		if( FCmpDst )
			{
			delete FCmpDst;
			FCmpDst = NULL;
			}

		if( FCmpSrc )
			{
			delete FCmpSrc;
			FCmpSrc = NULL;
			}
		}
	catch( Exception &e )
		{
		ShowMessage( e.Message );
		}

	BREnd();
	return( eRetCode );
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::BRBegin(const AnsiString &_aBRFilePath,const AnsiString &_aBRFileName )
	{
	AnsiString aTemp;

	aBRFilePath = _aBRFilePath.UpperCase();
	aBRFileName = _aBRFileName.UpperCase();

	IOBuffer	= NULL;

	try
		{
		IOBuffer = new unsigned char[ BR_IO_BUFSIZE ];
		}

	catch( Exception &e )
		{
		return( BR_ERR_EXHAUSTED_MEMORY );
		}

	// Verif validite fichier
	if(aBRFilePath.IsEmpty() || (aBRFilePath[1] < 'A' || aBRFilePath[1] > 'Z') && aBRFilePath.AnsiPos("\\\\") == 0)
		{
		BREnd();
		return( BR_ERR_BR_PATH_NOT_FOUND );
		}

	if( aBRFilePath.Length() == 2 && aBRFilePath[2] == ':' )
		aBRFilePath += "\\";

   //Ce n'est ni une lettre (A:\), ni un chemin UNC
	if(   (aBRFilePath[2] != ':'  || aBRFilePath[3] != '\\')
      && (aBRFilePath[1] != '\\' || aBRFilePath[2] != '\\'))
		{
		BREnd();
		return( BR_ERR_BR_PATH_NOT_FOUND );
		}

	if(aBRFilePath[1] == 'A' || aBRFilePath[1] == 'B')
		bIsBROnFloppy = true;
	else
		{
		bIsBROnFloppy = false;

		// Test l'existance du repertoire sur disque dur
		/////////////////////////////////////////////////
		aTemp = aBRFilePath;
		if( aTemp[aTemp.Length()] == '\\' )
			aTemp[aTemp.Length()] == '\0';

		//if( !DirectoryExists( aTemp ))
		if( access( aTemp.c_str(), 0 ) == -1 )
			{
			if( !ForceDirectories(aTemp.c_str()))
				{
				BREnd();
				return( BR_ERR_BR_PATH_NOT_FOUND );
				}
			}
		}

	// Copie du nom du fichier BR avec extension automatique
	if( aBRFileName.Pos(".") == 0 )
		aBRFileName += BR_DEFAULT_BRFILE_EXT;

	// Header de backup par défaut
	memset( &brHeader, 0, sizeof( brHeader));
	brHeader.UserNumVer = MAKELONG( NUM_VERS_1, NUM_VERS_2 );
	lBRLeftSize 		= 0L;

	return( BR_OK );
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::BREnd()
	{
	if( ListPathToBackup )
		delete ListPathToBackup;
	ListPathToBackup = NULL;

	if( IOBuffer )
	    delete []IOBuffer;

	IOBuffer = NULL;
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
int __fastcall CBackupRestore::GetCodeErr(const AnsiString &aErrName )
	{
	int i = 0;

	while( i < NB_CODES_RET )
		{
		if( aBRErrMsg[i] == aErrName )
			return( i );
		i ++;
		}

	return( 0 );
	}




////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
bool __fastcall CBackupRestore::BRIsGoodBRFile(const AnsiString &aBRFile )
	{
	BR_HEADER brTmp;

	// Lecture de l'en-tête du fichier backup
	/////////////////////////////////////////
	try
		{
		FBackup = new TFileStream( aBRFile, fmOpenRead );
		}

	catch( Exception &e )
		{
		if( bForBackup )
			return( true );
		else
			return( false );
		}

	try
		{
		if( FBackup->Read( &brTmp, sizeof( brTmp )) == (signed)sizeof( brTmp ))
			{
            delete FBackup;
            FBackup = NULL;

            if( brTmp.Tag == BR_HEADER_TAG )
                {
                if( bForBackup )
                    {
                    // Ce fichier est valide s'il ne fait pas partie du jeu de sauvegarde courant */
                    return( brTmp.tiBackup != brHeader.tiBackup );
                    }
                else
                    {
                    // Ce fichier est valide si c'est celui attendu
                    return( brTmp.NumDisk == brHeader.NumDisk);
                    }
				}
			}
		// Fermeture du fichier non reconnu comme un fichier backup */
		delete FBackup;
        FBackup = NULL;

		if( bForBackup )
			return( true );
		else
			return( false );
	   }
   catch( Exception &e )
	   {
	   ShowMessage( e.Message );
	   }
	return( false );
	}




////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::BRInsertFloppy()
	{
	BR_CODE eRetCode 	= BR_REDO;
	bool	bForCancel	= false;

	try
		{
		// Fermeture du Fichier Backup s'il est ouvert
		if(( eRetCode = CloseStreamBackup()) != BR_REDO )
			return( eRetCode );

		// Incrément du n° de disque à insérer
		brHeader.NumDisk ++;

		// Test si Backup a faire sur Disc et taille suffisante
		if( bForBackup && !bIsBROnFloppy && ( brHeader.NumDisk > 1 ))
			{
			// Erreur: On demande un nouveau disque dur pour sauvegarder
			// i.e. le disque dur est plein !!!
			return( BR_ERR_DEST_FILE_WRITE_ERROR );
			}

		do
			{
			// Insertion d'un nouveau disque avec demande des suivi de la procedure
			///////////////////////////////////////////////////////////////////////
			if( bIsBROnFloppy )
				{
				bForCancel = false;

				if( OnInsertFloppy && !FAutoEvents.Contains(eBRInsertFloppy))
					OnInsertFloppy( this, brHeader.NumDisk, aBRFilePath, bForCancel, bForBackup );
				else
					OnOwnInsertFloppy( this, brHeader.NumDisk, aBRFilePath, bForCancel, bForBackup );

				// Abandon de la procedure
				if( bForCancel )
					{
					eRetCode = BR_ERR_ACTION_CANCELED;
					break;
					}
				}

			// Teste de l'existance du lecteur et de son mode d'acces
			/////////////////////////////////////////////////////////
			eRetCode = DriveStatus(aBRFilePath);

			// Erreur matérielle
			////////////////////
			if(( bForBackup && eRetCode != BR_OK ) || ( !bForBackup && eRetCode == BR_ERR_DRIVE_UNKNOW ))
				{
				// Erreur matérielle
				bForCancel = true;
				if( OnHardError && !FAutoEvents.Contains(eBRHardError))
					OnHardError( this, BR_ERR_DRIVE_UNKNOW, aBRErrMsg[ eRetCode ] + aBRFilePath[1], bForCancel, bForBackup );
				else if( FAutoEvents.Contains(eBRHardError))
					OnOwnHardError( this, BR_ERR_DRIVE_UNKNOW, aBRErrMsg[ eRetCode ] + aBRFilePath[1], bForCancel, bForBackup );

				if( !bIsBROnFloppy || bForCancel )
					{
					// Abandon sur erreur matérielle
					eRetCode = BR_ERR_ACTION_CANCELED;
					break;
					}

				// Demande de réinsertion d'une disquette valide
				continue;
				}

			// Vérification de la validité du fichier backup sur la Dk
			//////////////////////////////////////////////////////////
			eRetCode 	= BR_REDO;

			// Cas d'une diskette
			/////////////////////
			if( bIsBROnFloppy )
				{
				// Test de la nouvelle diskette inseree
				///////////////////////////////////////
				if( !BRIsGoodBRFile( MakeFullFile(  aBRFilePath, aBRFileName )))
					{
					// Demande de réinsertion d'une disquette valide
					continue;
					}

				// Destruction du ou des anciens fichiers de la nouvelle disquette
				//////////////////////////////////////////////////////////////////
				if( bForBackup )
					DeleteFilesBeforeBackup();
				}

			// Cas d'un disque non amovible
			///////////////////////////////
			else if( bForBackup )
				DeleteFile( MakeFullFile(  aBRFilePath, aBRFileName ));

			// Lecture de la place restante sur le disque
			/////////////////////////////////////////////
			if( bForBackup )
				{
				if( !IsDiskSizeOk(aBRFilePath, eRetCode))
					{
					// Demande de réinsertion d'une disquette valide
					continue;
					}
				}

			// Ouverture du fichier BR
			//////////////////////////
			OpenBR( eRetCode );

			}while(eRetCode == BR_REDO );
		}

   catch( Exception &e )
	   {
	   ShowMessage( e.Message );
	   }

   return( eRetCode );
   }



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::CloseStreamBackup()
	{
	BR_CODE eRetCode = BR_REDO;

	try
		{
		if( FBackup )
			{
			delete FBackup;
            FBackup = NULL;
			}
		}
	catch( Exception &e )
		{
		eRetCode = bForBackup ? BR_ERR_DEST_FILE_WRITE_ERROR : BR_ERR_SRC_FILE_READ_ERROR;
		}

	return( eRetCode );
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::DeleteFilesBeforeBackup()
	{
	AnsiString aTemp;

	try
		{
		// Destruction de tous les fichiers du drive
		////////////////////////////////////////////
		if( bDeleteFilesBeforeBackup )
         EicDirDeleteContenu(aBRFilePath);

		// Destruction du BR existant
		/////////////////////////////
		else
			{
			aTemp = MakeFullFile(  aBRFilePath, aBRFileName );
			if( FileExists( aTemp ))
				{
				// Effacement attributs ancien fic backup Dk
				SetFileAttributes( aTemp.c_str(), FILE_ATTRIBUTE_NORMAL);
				DeleteFile( aTemp );
				}
			}
		}
	catch( Exception &e )
		{
		ShowMessage( e.Message );
		}
	}





////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
bool __fastcall CBackupRestore::IsDiskSizeOk(const AnsiString &aPath, BR_CODE &eRetCode )
	{
	bool bForCancel;

	try
		{
		while( 1 )
			{
			// Création du répertoire de sauvegarde
			if( ForceDirectories(aBRFilePath.c_str()))
				{
				// Notification de disque prêt
				//////////////////////////////
				bForCancel = false;
				if( OnBackupMediaReady )
					OnBackupMediaReady( this, brHeader.NumDisk, aBRFilePath, bForCancel );

				if( bForCancel )
					{
					// Abandon du backup
					eRetCode = BR_ERR_ACTION_CANCELED;
					break;
					}

            Sysutils::GetDiskFreeSpaceEx(aPath.c_str(), lBRLeftSize, NULL, NULL);

            if(lBRLeftSize >= BR_MIN_BACKUP_FLOPPY_FREE_SPACE)
               {
               if( bIsBROnFloppy && ( brHeader.NumDisk == 1 ))
                  lBRLeftSize -= KEEP_BYTES_ON_FIRST_FLOPPY;
               if( lBRLeftSize >= BR_MIN_BACKUP_FLOPPY_FREE_SPACE )
                  break;
               }
				}

			// Espace insuffisant
			/////////////////////
			bForCancel = true;
			if( OnHardError && !FAutoEvents.Contains(eBRHardError))
				OnHardError( this, BR_ERR_DRIVE_OUTOFSPACE, aBRErrMsg[BR_ERR_DRIVE_OUTOFSPACE], bForCancel, bForBackup );
			else if( FAutoEvents.Contains(eBRHardError))
				OnOwnHardError( this, BR_ERR_DRIVE_OUTOFSPACE, aBRErrMsg[BR_ERR_DRIVE_OUTOFSPACE], bForCancel, bForBackup );

			if( !bIsBROnFloppy || bForCancel )
				{
				// Abandon sur erreur matérielle
				lBRLeftSize = 0L;
				eRetCode    = BR_ERR_ACTION_CANCELED;
				break;
				}
			}

		if( lBRLeftSize == 0L )
			{ // La disquette n'a pas assez d'espace libre
			if( eRetCode != BR_REDO)
				return( false );
			else
				{
				// Réintroduction d'une disquette
				if( !bIsBROnFloppy )
					throw EAbort("Not a floppy");
				return( false );
				}
			}
		}
   catch( Exception &e )
	   {
	   ShowMessage( e.Message );
	   }

	return( true );
	}




////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::OpenBR( BR_CODE &eRetCode )
	{
   AnsiString aTemp;

   try
		{
		aTemp = MakeFullFile( aBRFilePath, aBRFileName );

		while(1)
			{
			if( bForBackup )
				{
				// Creation (en ecrasement) du fichier de sauvegarde
				try
					{
					FBackup = new TFileStream( aTemp, fmCreate | fmOpenWrite | fmShareExclusive );
					}

				catch( Exception &e )
					{
					// Erreur fatale de cr‚ation du fichier de sauvegarde
					eRetCode = BR_ERR_DEST_FILE_WRITE_ERROR;
					}

				if( eRetCode != BR_ERR_DEST_FILE_WRITE_ERROR )
					{
					if(( eRetCode = BackupBuffer( &brHeader, sizeof( brHeader ))) == BR_OK )
						{
						// Cr‚ation du fichier de sauvegarde Ok
						lBRLeftSize -= sizeof( brHeader );

						// Nouveau disque de sauvegarde valide
						eRetCode = BR_OK;
						break;
						}
					}
				// Erreur fatale de cr‚ation du fichier de sauvegarde
				eRetCode = BR_ERR_DEST_FILE_WRITE_ERROR;
				}

			else
				{
				// Ouverture en lecture seule du fichier à restaurer
				try
					{
					FBackup = new TFileStream( aTemp, fmOpenRead );
					}

				catch( Exception &e )
					{
					// Erreur fatale d'ouverture du fichier à restaurer
					eRetCode = BR_ERR_SRC_FILE_READ_ERROR;
					}


				if( eRetCode != BR_ERR_SRC_FILE_READ_ERROR )
					{
					if(( lBRLeftSize = FBackup->Size ) >= 0L )
						{
						if(( eRetCode = RestoreBuffer( &brHeader, sizeof( brHeader ))) == BR_OK )
							{
							// Nouveau disque de sauvegarde valide
							eRetCode = BR_OK;
							break;
							}
						}
					}
				// Erreur fatale d'ouverture du fichier à restaurer
				eRetCode = BR_ERR_SRC_FILE_READ_ERROR;
				}

			// Abandon sur erreur
			if( FBackup )
    			{
	    		delete FBackup;
                FBackup = NULL;
			    }
			break;
			}
        }
	catch( Exception &e )
		{
		ShowMessage( e.Message );
		}
	}



/////////////////////////
/////////////////////////
////
////    BackupBuffer
////
/////////////////////////
/////////////////////////
BR_CODE __fastcall CBackupRestore::BackupBuffer( void *Datas, long lLenDatas )
	{
	BR_CODE eRetCode;

	if( lLenDatas == 0L )
		return( BR_OK );

	// Verification de l'espace libre sur disque
	if( lBRLeftSize == 0L )
		{
		if(( eRetCode = BRInsertFloppy()) != BR_OK )
			return( eRetCode );
		}

	try
		{
		if( FBackup->Write( Datas, (unsigned)lLenDatas ) != (int)lLenDatas )
			return( BR_ERR_DEST_FILE_WRITE_ERROR );
		else
			{
			lBRLeftSize -= lLenDatas;
			return( BR_OK );
			}
		}

	catch( Exception &e )
		{
		return( BR_ERR_DEST_FILE_WRITE_ERROR );
		}
	}




/////////////////////////
/////////////////////////
////
////    BackupBuffer
////
/////////////////////////
/////////////////////////
BR_CODE __fastcall CBackupRestore::BackupBuffer( TFileStream *F, long lLenDatas )
	{
	BR_CODE eRetCode;

	if( lLenDatas == 0L )
		return( BR_OK );

	// Verification de l'espace libre sur disque
	if( lBRLeftSize == 0L )
		{
		if(( eRetCode = BRInsertFloppy()) != BR_OK )
			return( eRetCode );
		}

	try
		{
		if( FBackup->CopyFrom( F, lLenDatas ) != lLenDatas )
			return( BR_ERR_DEST_FILE_WRITE_ERROR );
		else
			{
			lBRLeftSize -= lLenDatas;
			return( BR_OK );
			}
		}

	catch( Exception &e )
		{
		return( BR_ERR_DEST_FILE_WRITE_ERROR );
		}
	}




/////////////////////////
/////////////////////////
////
////    RestoreBuffer
////
/////////////////////////
/////////////////////////
BR_CODE __fastcall CBackupRestore::RestoreBuffer( void *Datas, long lLenDatas )
	{
	BR_CODE eRetCode;

	if( lLenDatas == 0L )
		return( BR_OK );


	// Vérification de la fin du fichier BR
	if( lBRLeftSize == 0L )
		{
		if(( eRetCode = BRInsertFloppy()) != BR_OK )
			return( eRetCode );
		}

	try
		{
		if( FBackup->Read( Datas, (unsigned)lLenDatas ) != (int)lLenDatas )
			return( BR_ERR_SRC_FILE_READ_ERROR );
		else
			{
			lBRLeftSize -= lLenDatas;
			return( BR_OK );
			}
		}

	catch( Exception &e )
		{
		return( BR_ERR_SRC_FILE_READ_ERROR );
		}
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::BackupPattern( 	unsigned short uhUserDataLen,
											const unsigned char *sUserDesc )
	{
	TFileStream    	*FSrc;
	BR_CODE   		eRetCode;
	BR_FILEDESC	   	sFileDesc = { 0 };
	AnsiString 	   	aTemp;
	AnsiString     	aSrcFilePattern;
	unsigned short 	uhNbPatternFiles;
	unsigned short 	uhTmp;
	long		   	lPatternDataSize = 0;
	unsigned short 	uhSizeHeader;
   TSearchRec OptionsRech;
   unsigned short Jour, Mois, Annee, Heure, Minute, Seconde, MilliS;
   TDateTime DateFichier;
   AnsiString RepInterne;

	// Calcul de la taille des fichiers du pattern
	//////////////////////////////////////////////
   try
		{
		aTemp = MakeFullFile( aSrcPathPattern, "*.*" );

		// Erreur: Le premier fichier de ce pattern a été effacé (Réseau)
//      if(FindFirst( aTemp.c_str(), faAnyFile	, OptionsRech) != 0)
      if(FindFirst( aTemp.c_str(), faReadOnly | faHidden | faSysFile | faArchive, OptionsRech) != 0)
			return(BR_ERR_SRC_FILE_DELETED_DURING_BACKUP);

		for( uhNbPatternFiles = 1, lPatternDataSize = OptionsRech.Size; FindNext(OptionsRech) == 0;
			lPatternDataSize += OptionsRech.Size, uhNbPatternFiles ++);
      FindClose(OptionsRech);

      if(FindFirst( aTemp.c_str(), faReadOnly | faHidden | faSysFile | faArchive, OptionsRech) != 0)
			// Erreur: Le premier fichier de ce pattern a été effacé (Réseau)
			return( BR_ERR_SRC_FILE_DELETED_DURING_BACKUP );

		if( aSrcPathPattern.IsEmpty())
			aSrcPathPattern = ".\\";

		// Sauvegarde du descripteur du pattern
		///////////////////////////////////////
      //Extrait le nom du répertoire par rapport au répertoire d'origine
      RepInterne = EXTRAIRE_CH(aSrcPathPattern, Directory.Length()+1, aSrcPathPattern.Length());

		uhTmp = (unsigned short)(RepInterne.Length() + 1);
		if(( eRetCode = BackupBuffer( &uhTmp, sizeof( uhTmp ))) != BR_OK )
			return( eRetCode );
		if(( eRetCode = BackupBuffer( RepInterne.c_str(), uhTmp )) != BR_OK )
			return( eRetCode );
		if(( eRetCode = BackupBuffer( &lPatternDataSize, sizeof( lPatternDataSize ))) != BR_OK )
			return( eRetCode );
		if(( eRetCode = BackupBuffer( &uhNbPatternFiles, sizeof( uhNbPatternFiles ))) != BR_OK )
			return( eRetCode );
		if(( eRetCode = BackupBuffer( &uhUserDataLen, sizeof( unsigned short ))) != BR_OK )
			return( eRetCode );
		if(( eRetCode = BackupBuffer( IOBuffer, uhUserDataLen )) != BR_OK )
			return( eRetCode );

		// Initialisations pour ce nouveau pattern
		lCurDataSize = 0L;

		// Sauvegarde des fichiers du pattern
		/////////////////////////////////////
		do
			{
			// Compression des données du fichier
			/////////////////////////////////////
			// Préparation du nom du fichier à sauvegarder
 			aTemp = MakeFullFile( aSrcPathPattern, OptionsRech.Name);

 			// Ouverture du fichier à compresser
			try
				{
				FCmpSrc = new TFileStream( aTemp, fmOpenRead );
				}

			catch( Exception &e )
				{
				// Abandon sur erreur d'ouverture fichier source
				return( BR_ERR_SRC_FILE_READ_ERROR );
				}

			if( OnBackupFile )
				OnBackupFile( this, OptionsRech.Name );

			if( BarProgress )
				{
				BarProgress->PBarFile->Position = 0;
				BarProgress->LFileName->Caption = AnsiString(OptionsRech.Name);
				BarProgress->PAll->Refresh();
				BarProgress->GBoxBR->Refresh();
				BarProgress->GBoxDir->Refresh();
				BarProgress->GBoxFile->Refresh();
				BarProgress->LFileName->Refresh();
				}

			// Compression du fichier à sauvegarder
			//////////////////////////////////////
			lCmpSrcSize = OptionsRech.Size;
			if(( eRetCode = BRImplodeFile()) != BR_OK )
				{
				// Erreur durant la compression du fichier à sauvegarder
                if( FCmpSrc )
                    {
                    delete FCmpSrc;
                    FCmpSrc = NULL;
                    }
				break;
				}

			// Sauvegarde du descripteur du fichier
			///////////////////////////////////////
			strcpy( sFileDesc.pszName, OptionsRech.Name.c_str() );
			sFileDesc.lSize    		= OptionsRech.Size;
			sFileDesc.fAttrib  		= (unsigned short)OptionsRech.Attr;     //OptionsRech.Attrib

         DateFichier = FileDateToDateTime(OptionsRech.Time);
         DateFichier.DecodeTime(&Heure, &Minute, &Seconde, &MilliS);
         sFileDesc.uhLMTime = (Heure << 11) + (Minute << 5) + Seconde/2;

         DateFichier.DecodeDate(&Annee, &Mois, &Jour);
         sFileDesc.uhLMDate = ((Annee-1980) << 9) + (Mois << 5) + Jour;

			uhSizeHeader 			= (unsigned short)( sizeof( BR_FILEDESC ) - MAXPATH + strlen( sFileDesc.pszName ));

			if( lCmpDstSize < OptionsRech.Size )
				{
				// Le fichier est compressé (taille favorable)
				// => On considère qu'on a déjà sauvegardé la taille gagnée par la compression
				lCurDataSize += ( OptionsRech.Size - lCmpDstSize );

				// => Il faut sauvegarder le fichier compressé
				FSrc               = FCmpDst;
				lLeftFileSize      =
				OptionsRech.Size     =
				sFileDesc.lCmpSize = lCmpDstSize;
				sFileDesc.uhFlags  = FDF_COMPRESSED;
				}

			else
				{
				// La compression n'a rien donné (taille défavorable)
				// => Il faut sauvegarder le fichier d'origine (celui qui était à compresser)
				FSrc               = FCmpSrc;
				lLeftFileSize      =
				sFileDesc.lCmpSize = OptionsRech.Size;
				sFileDesc.uhFlags  = FDF_NULL;
				}

			// Ecriture du descripteur
			//////////////////////////
			if(( eRetCode = BackupBuffer( &uhSizeHeader, sizeof( unsigned short ))) != BR_OK )
				{
				// Erreur durant l'écriture du descripteur de fichier
				if( FCmpSrc )
               {
    				delete FCmpSrc;
               FCmpSrc = NULL;
               }
				break;
				}
			if(( eRetCode = BackupBuffer( &sFileDesc, uhSizeHeader - strlen( sFileDesc.pszName ))) != BR_OK )
				{
				// Erreur durant l'écriture du descripteur de fichier
				if( FCmpSrc )
               {
    				delete FCmpSrc;
               FCmpSrc = NULL;
               }
				break;
				}
			if(( eRetCode = BackupBuffer( &sFileDesc.pszName, strlen( sFileDesc.pszName ))) != BR_OK )
				{
				// Erreur durant l'écriture du descripteur de fichier
				if( FCmpSrc )
                    {
    				delete FCmpSrc;
                    FCmpSrc = NULL;
                    }
				break;
				}

			// Sauvegarde des données du fichier (compressées ou non)
			/////////////////////////////////////////////////////////
			try
				{
				FSrc->Seek( 0, soFromBeginning );
				}

			catch( Exception &e )
				{
				return( BR_ERR_SRC_FILE_READ_ERROR );
				}


			while( lLeftFileSize )
				{
				// Sauvegarde d'un bloc du fichier source
				// Insertion éventuelle d'une nouvelle disquette
				if( lBRLeftSize <= 0L)
					{
					if(( eRetCode = BRInsertFloppy()) == BR_OK )
						{
						// Notification
						if( OnNewFloppy )
							OnNewFloppy( this, brHeader.NumDisk, OptionsRech.Name, bForBackup );

						// Rappel de la progression
						if( OnPercents && !FAutoEvents.Contains(eBRPercents))
							{
							OnPercents( this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
									   (unsigned short)((( OptionsRech.Size - lLeftFileSize ) * 100L )
									   / OptionsRech.Size ),	bForBackup );
							}
						else if( FAutoEvents.Contains(eBRPercents))
							{
							OnOwnPercents( 	this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
											(unsigned short)((( OptionsRech.Size - lLeftFileSize ) * 100L )
											/ OptionsRech.Size ),	bForBackup );
							}
						}
					else
						{
						// Erreur durant l'insertion du nouveau disque
						break;
						}
					}

				// Calcul de la taille du bloc à sauvegarder
				////////////////////////////////////////////
				uSrcBlockSize = ( lLeftFileSize < BR_IO_BUFSIZE ) ? (unsigned int)lLeftFileSize : BR_IO_BUFSIZE;
				if((long)uSrcBlockSize > lBRLeftSize )
					   uSrcBlockSize = (unsigned int)lBRLeftSize;

				// Lecture du bloc à sauvegarder
				////////////////////////////////
				if(( eRetCode = BackupBuffer( FSrc, uSrcBlockSize )) != BR_OK )
					break;

				// MAJ des tailles relatives au backup
				//////////////////////////////////////
				lCurDataSize  += (long)uSrcBlockSize;
				lLeftFileSize -= (long)uSrcBlockSize;

				// Avancement de la sauvegarde
				if( OnPercents && !FAutoEvents.Contains(eBRPercents))
					{
					OnPercents( this, 0, (unsigned short)(( lCurDataSize * 100L) / lPatternDataSize ),
								(unsigned short)((( OptionsRech.Size - lLeftFileSize) * 100L )
								/ OptionsRech.Size ), bForBackup );
					}
				else if( FAutoEvents.Contains(eBRPercents))
					{
					OnOwnPercents( 	this, 0, (unsigned short)(( lCurDataSize * 100L) / lPatternDataSize ),
									(unsigned short)((( OptionsRech.Size - lLeftFileSize) * 100L )
									/ OptionsRech.Size ), bForBackup );
					}
				}

			// Fermeture du fichier sauvegardé (compressé ou non)
			if( FCmpSrc )
                {
    			delete FCmpSrc;
                FCmpSrc = NULL;
                }

			// Erreur durant la sauvegarde du fichier source
			if( eRetCode != BR_OK)
				break;

			// Fichier correctement sauvegardé
			FCmpDst->Seek(0, soFromBeginning);
			}while( FindNext(OptionsRech) == 0 );

		FindClose(OptionsRech);

		if( FCmpSrc )
            {
            delete FCmpSrc;
            FCmpSrc = NULL;
            }

		if( eRetCode == BR_OK )
			{
			// Sauvegarde de chaque fichier trouvé dans le pattern Ok
			// mais un fichier a pû être effacé (Réseau) durant la sauvegarde du pattern
			return(( lCurDataSize == lPatternDataSize ) ? BR_OK : BR_ERR_SRC_FILE_DELETED_DURING_BACKUP );
			}
		else
			{
			// Erreur durant la sauvegarde d'un fichier du pattern
			return( eRetCode );
			}
		}
	catch( Exception &e )
		{
		ShowMessage( e.Message );
		}
	return( eRetCode );
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::RestorePattern( 	unsigned short 	&uhUserDataLen,
											unsigned char 	*sUserDesc,
											const AnsiString &aTmpFile )
	{
	TFileStream    	*FDst;
	BR_FILEDESC    	brfd;
	BR_CODE   		eRetCode;
	AnsiString 	   	aTemp;
	int            	hFile;	 // handle du fichier de restauration pour changement date/time
	bool           	bDoNotRestorePattern; // TRUE pour pas restaurer le pattern
	bool           	bForCancel;
	long		   	lPatternDataSize = 0;
	unsigned short 	uhNbPatternFiles;
	unsigned short 	uhPercents;
	unsigned int   	uDstBlockSize;        // Taille d'un bloc de fhDst à restaurer
	unsigned char	uhSizeHeader;
   TSearchRec FileSearch;
   unsigned short Jour, Mois, Annee, Heure, Minute, Seconde;
   TDateTime DateFichier;

	try
		{
		// Lecture du descripteur de pattern
		////////////////////////////////////
		/*** Lecture du descripteur ***/
		if(( eRetCode = RestoreBuffer( &lPatternDataSize, sizeof( long ))) != BR_OK )
			return( eRetCode );
		if(( eRetCode = RestoreBuffer( &uhNbPatternFiles, sizeof( uhNbPatternFiles ))) != BR_OK )
			return( eRetCode );
		if(( eRetCode = RestoreBuffer( &uhUserDataLen, sizeof( unsigned short ))) != BR_OK )
			return( eRetCode );
//		if(( eRetCode = RestoreBuffer( &sUserData, uhUserDataLen )) != BR_OK )
        if(( eRetCode = RestoreBuffer( sUserDesc, uhUserDataLen )) != BR_OK )
			return( eRetCode );

		// Restauration du descripteur de pattern Ok

		// Restauration du pattern
		//////////////////////////
		// Notification
		bForCancel 				= false;
		bDoNotRestorePattern	= false;
		if( OnRestorePattern )
			{
			OnRestorePattern( 	this, lPatternDataSize, uhNbPatternFiles, bDoNotRestorePattern, uhUserDataLen, sUserDesc,
								aSrcPathPattern, bForCancel );
			}

		// Restauration dans le repertoire indique par l'informaticien
		//////////////////////////////////////////////////////////////
		if( !FDirectory.IsEmpty())
			{
         if( aSrcPathPattern.Pos(FDirectory) != 1 )
            {
            if( aSrcPathPattern[aSrcPathPattern.Length()] != '\\' )
               aSrcPathPattern += "\\";
            aSrcPathPattern = FDirectory + aSrcPathPattern.SubString( 4, aSrcPathPattern.Length());
            }
			}

		if( BarProgress )
			{
			BarProgress->LDirectory->Caption = aSrcPathPattern;
			BarProgress->LDirectory->Refresh();
			}

		// Arrêt du restore
		if( bForCancel )
			return( BR_STOP );



		// Restauration des fichiers du pattern
		///////////////////////////////////////
		lCurDataSize = 0L;

		while( uhNbPatternFiles && eRetCode == BR_OK )
			{
			memset( &brfd, 0, sizeof( BR_FILEDESC ));
			// Lecture du descripteur du fichier à restaurer
			////////////////////////////////////////////////
			if(( eRetCode = RestoreBuffer( &uhSizeHeader, sizeof( unsigned short ))) != BR_OK )
				break;

			if(( eRetCode = RestoreBuffer( &brfd, sizeof( BR_FILEDESC ) - MAXPATH ))!= BR_OK )
				break;
			if(( eRetCode = RestoreBuffer( &brfd.pszName, uhSizeHeader + MAXPATH - sizeof( BR_FILEDESC ))) != BR_OK )
				{
				// Erreur durant la lecture du descripteur de fichier
				break;
				}

			FCmpSrc = new TFileStream( aTmpFile, fmCreate | fmOpenReadWrite | fmShareExclusive );
			// Vérification de l'intégrité du descripteur
			/////////////////////////////////////////////
			// Drapeau de compression
			if( brfd.uhFlags == FDF_COMPRESSED )
				{
				if( brfd.lCmpSize >= brfd.lSize )
					{
					eRetCode = BR_ERR_BR_FILE_CORRUPTED;
					break;
					}
				}

			else if( brfd.uhFlags == FDF_NULL)
				{
				if( brfd.lCmpSize != brfd.lSize )
					{
					eRetCode = BR_ERR_BR_FILE_CORRUPTED;
					break;
					}
				}

			else
				{
				// Descripteur invalide
				eRetCode = BR_ERR_BR_FILE_CORRUPTED;
				break;
				}

			// Nom du fichier
			if( !*brfd.pszName || ( strlen( brfd.pszName ) >= sizeof( brfd.pszName )))
				{
				eRetCode = BR_ERR_BR_FILE_CORRUPTED;
				break;
				}

			// Initailisation de la (non) restauration du fichier
			/////////////////////////////////////////////////////
			lLeftFileSize = brfd.lCmpSize;

			// Notification de restauration du fichier
			bForCancel = false;
			if( OnRestoreFile )
				OnRestoreFile( this, brfd, aSrcPathPattern, bForCancel );

			if( BarProgress )
				{
				BarProgress->PBarFile->Position = 0;
				BarProgress->LFileName->Caption = AnsiString(brfd.pszName);
				BarProgress->PAll->Refresh();
				BarProgress->GBoxBR->Refresh();
				BarProgress->GBoxDir->Refresh();
				BarProgress->GBoxFile->Refresh();
				BarProgress->LFileName->Refresh();
				}

			if( bForCancel )
				{
				// Arrêt du restore
				return( BR_STOP );
				}

			if( bDoNotRestorePattern )
				{
				// Ce fichier n'est pas à restaurer
				*brfd.pszName = '\0';
				}

			else
				{
				// Création (en écrasement) du fichier à restaurer
				//////////////////////////////////////////////////
				if( !bDoNotRestorePattern && *brfd.pszName )
					{
					// Ce fichier doit être restauré
					aTemp = MakeFullFile( aSrcPathPattern, brfd.pszName );

					// RAZ des flags du fichier existant
					SetFileAttributes( aTemp.c_str(), FILE_ATTRIBUTE_NORMAL );

					// Création du fichier en écrasement avec RAZ du fichier s'il existe
					////////////////////////////////////////////////////////////////////
					try
						{
						if( access( aSrcPathPattern.c_str(), 0 ) == -1 )
							{
							if( !ForceDirectories(aSrcPathPattern.c_str()))
								eRetCode = BR_ERR_DEST_FILE_WRITE_ERROR;
							}
						FCmpDst = new TFileStream( aTemp, fmCreate | fmOpenWrite | fmShareExclusive );
						}

					catch( Exception &e )
						{
						// Abandon sur erreur d'ouverture fichier cible
						eRetCode = BR_ERR_DEST_FILE_WRITE_ERROR;
						break;
						}

					if( brfd.uhFlags == FDF_COMPRESSED )
						{
						// On va restaurer le fichier compressé du BR dans le fichier source à décompresser
						FDst = FCmpSrc;
						FDst->Seek( 0, soFromBeginning );
						}
					else
						{
						// On va restaurer directement le fichier de destination (car il n'est pas compressé)
						FDst = FCmpDst;
						}
					}

				else
					{
					// Ce fichier n'est pas à restaurer => %tage de restauration à 0
					uhPercents = 0;
					}
				}

			// Restauration des données du fichier
			//////////////////////////////////////
			while( lLeftFileSize )
				{
				// Restauration d'un bloc du fichier source
				///////////////////////////////////////////
				// Insertion éventuelle d'une nouvelle disquette
				if( lBRLeftSize <= 0L )
					{
					if(( eRetCode = BRInsertFloppy()) == BR_OK )
						{
						// Notification
						if( OnNewFloppy )
							OnNewFloppy( this, brHeader.NumDisk, brfd.pszName, bForBackup );

						if( !bDoNotRestorePattern )
							{
							// Rappel de la progression
							if( *brfd.pszName )
								{
								// %tage de restauration du fichier
								uhPercents = (unsigned short)((( brfd.lCmpSize - lLeftFileSize ) * 100L) / brfd.lCmpSize );
								}
							else
								{
								// Ce fichier n'est pas à restaurer
								uhPercents = 0;
								}

							if( OnPercents && !FAutoEvents.Contains(eBRPercents))
								OnPercents( this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ), uhPercents, bForBackup );
							else if( FAutoEvents.Contains(eBRPercents))
								OnOwnPercents( this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ), uhPercents, bForBackup );
							}
						}

					else
						{ // Erreur durant l'insertion du nouveau disque
						break;
						}
					}

				if( !*brfd.pszName )
					{
					// Ce fichier ne doit pas être restauré
					if( lLeftFileSize <= lBRLeftSize )
						{
						// D'autres données sont à restaurer depuis le fichier backup de la Dk
						if( FBackup->Seek( lLeftFileSize, soFromCurrent ) <= 0L )
							{
							// Erreur de lecture du fichier backup
							eRetCode = BR_ERR_SRC_FILE_READ_ERROR;
							break;
							}

						lBRLeftSize   -= lLeftFileSize;
						lCurDataSize  += lLeftFileSize + ( brfd.lSize - brfd.lCmpSize );
						lLeftFileSize  = 0L;
						}

					else
						{
						// Ce fichier à ne pas restaurer va jusqu'à la fin du fichier backup de la Dk
						lLeftFileSize -= lBRLeftSize;
						lCurDataSize  += lBRLeftSize;
						lBRLeftSize    = 0L;
						}

					if( !bDoNotRestorePattern )
						{
						// On ne restaure pas ce fichier du pattern
						if( OnPercents && !FAutoEvents.Contains(eBRPercents))
							{
							OnPercents( this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
										uhPercents, bForBackup );
							}
						else if( FAutoEvents.Contains(eBRPercents))
							{
							OnOwnPercents( 	this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
											uhPercents, bForBackup );
							}
						}

					continue;
					}

				// Calcul de la taille du bloc à restaurer
				//////////////////////////////////////////
				uDstBlockSize = ( lLeftFileSize < BR_IO_BUFSIZE ) ? (unsigned int)lLeftFileSize : BR_IO_BUFSIZE;
				if((long)uDstBlockSize > lBRLeftSize )
					uDstBlockSize = (unsigned int)lBRLeftSize;

				// Lecture et restauration du bloc
				//////////////////////////////
				if(( eRetCode = CopieBuffer( FBackup, FDst, uDstBlockSize )) != BR_OK )
					break;

				// MAJ des tailles relatives au restore
				lCurDataSize  += (long)uDstBlockSize;
				lLeftFileSize -= (long)uDstBlockSize;

				// Avancement de la restauration
				if( OnPercents && !FAutoEvents.Contains(eBRPercents))
					{
					OnPercents( this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
								(unsigned short)((( brfd.lCmpSize - lLeftFileSize ) * 100L ) / brfd.lCmpSize ),	bForBackup );
					}
				else if( FAutoEvents.Contains(eBRPercents))
					{
					OnOwnPercents( 	this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
									(unsigned short)((( brfd.lCmpSize - lLeftFileSize ) * 100L ) / brfd.lCmpSize ),	bForBackup );
					}
				}

			// Décompresion et fermeture du fichier restauré
			if( *brfd.pszName )
				{
				if( eRetCode == BR_OK)
					{
					// Fichier restauré entièrement
					if( brfd.uhFlags == FDF_COMPRESSED )
						{
						// Le fichier restauré doit être décompressé
						lCmpSrcSize = brfd.lCmpSize;
						lCmpDstSize = brfd.lSize;
						FDst->Seek( 0, soFromBeginning );
						if(( eRetCode = BRExplodeFile(FDst)) == BR_OK )
							{
							// On a restauré aussi la taille gagnée par la compression
							lCurDataSize += ( brfd.lSize - brfd.lCmpSize );

							// Rappel de la progression (100% du fichier restaurés)
							if( OnPercents && !FAutoEvents.Contains(eBRPercents))
								{
								OnPercents(	this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
											(unsigned short)100, bForBackup );
								}
							else if( FAutoEvents.Contains(eBRPercents))
								{
								OnOwnPercents( 	this, 0, (unsigned short)(( lCurDataSize * 100L ) / lPatternDataSize ),
												(unsigned short)100, bForBackup );
								}
							}
						}

					aTemp = MakeFullFile( aSrcPathPattern, brfd.pszName );
					if( FCmpDst )
			            {
            			delete FCmpDst;
			            FCmpDst = NULL;
            			}

					if( FCmpDst || eRetCode != BR_OK )
						{
						// Erreur de cloture du fichier destination ou bien erreur durant la décompression
						if( eRetCode == BR_OK )
							eRetCode = BR_ERR_DEST_FILE_WRITE_ERROR;
						DeleteFile( aTemp );
						break;
						}

					else
						{
						// Restauration des attributs du fichier
						SetFileAttributes( aTemp.c_str(), brfd.fAttrib );

						// Restauration Date/Heure d'origine du fichier
						///////////////////////////////////////////////
                  if ((hFile = FileOpen(aTemp, fmOpenReadWrite)) != -1)
							{
							// Changement de la date et heure
                     Seconde = (brfd.uhLMTime &   0x1F)*2 ;
                     Minute  = ((brfd.uhLMTime &  0x7E0) >> 5);
                     Heure   = ((brfd.uhLMTime & 0xF800) >> 11);
                     Jour  = brfd.uhLMDate &   0x1F;
                     Mois  = ((brfd.uhLMDate &  0x1E0) >> 5);
                     Annee = ((brfd.uhLMDate & 0xFE00) >> 9) + 1980;

                     DateFichier = TDateTime(Annee, Mois, Jour) + TDateTime(Heure, Minute, Seconde, 0);

                     FileSetDate(hFile, DateFichier.FileDate());
                     FileClose(hFile);
							}
						else
							{
							eRetCode = BR_ERR_DEST_FILE_WRITE_ERROR;
							break;
							}
						}
					}

				else
					{
					// Erreur durant la restauration du fichier cible (d'origine ou à décompresser)
					if( FCmpDst )
			            {
            			delete FCmpDst;
			            FCmpDst = NULL;
            			}
					aTemp = MakeFullFile( aSrcPathPattern, brfd.pszName );
					DeleteFile( aTemp );
					break;
					}
				}

			// Un fichier a été restauré entièrement ou pas du tout
			uhNbPatternFiles --;
			if( FCmpSrc )
                {
    			delete FCmpSrc;
	    		FCmpSrc = NULL;
                }
			}
		}
	catch( Exception &e )
		{
		ShowMessage( e.Message );
		}

	return( eRetCode );
	}




////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::CopieBuffer( TFileStream *Sour, TFileStream *Dest, long lLenDatas )
	{
	BR_CODE eRetCode;

	if( lLenDatas == 0L )
		return( BR_OK );

	// Vérification de la fin du fichier BR
	if( lBRLeftSize == 0L)
		{
		if(( eRetCode = BRInsertFloppy()) != BR_OK )
			return( eRetCode );
		}

	try
		{
		if( Dest->CopyFrom( Sour, lLenDatas ) != lLenDatas )
			{
			return( BR_ERR_SRC_FILE_READ_ERROR );
			}

		else
			{
			lBRLeftSize -= lLenDatas;
			return( BR_OK );
			}
		}

	catch( Exception &e )
		{
		return( BR_ERR_SRC_FILE_READ_ERROR );
		}
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::GetSubDirectories(const AnsiString &aPath )
	{
	AnsiString 	   	aTemp;
	bool			bFileFind	= false;
   TSearchRec  OptRecherche;

	// Calcul de la taille des fichiers du pattern
	//////////////////////////////////////////////
	try
		{
		aTemp = aPath + "*.*";

      if (FindFirst(aTemp, faReadOnly | faHidden | faSysFile | faArchive | faDirectory, OptRecherche) != 0)
			return;

		do
			{
			if(OptRecherche.Attr & faDirectory)
				{
				if(OptRecherche.Name[1] != '.')
					GetSubDirectories(aPath + OptRecherche.Name + "\\");
				}
			else
				{
				lAllFilesBR += OptRecherche.Size;
				bFileFind	= true;
				}
			}
         while(FindNext(OptRecherche) == 0);

      FindClose(OptRecherche);

		if(bFileFind)
			ListPathToBackup->Add( aPath );
		}
	catch( Exception &e )
		{
		ShowMessage( e.Message );
		}
	}



////////////////////////////////////////////////////
///
/// DriveStatus
///
/// Donne le statut d'un lecteur
///
/// P.E.: Lettre du drive a tester
///
/// P.S.: DRIVE_NOT_EXIST
///       DRIVE_PROTECT
///       DRIVE_NO_PROTECT
///
////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::DriveStatus(const AnsiString &aDir)
	{
	AnsiString 	aRepTest 	= "'";
	AnsiString	aFullFile;

	try
		{
		// Pré-conditions
		/////////////////
      if(   aBRFilePath.IsEmpty()
         || (UpperCase(aBRFilePath)[1] < 'A' || UpperCase(aBRFilePath)[1] > 'Z') && aBRFilePath.AnsiPos("\\\\") == 0)
			throw EAbort( aBRErrMsg[BR_ERR_DRIVE_UNKNOW] );

		// Test de l'existance du lecteur
		/////////////////////////////////
      if(GetDriveType(IncludeTrailingBackslash(ExtractFileDrive(aDir)).c_str()) == DRIVE_NO_ROOT_DIR)
         throw EAbort(aBRErrMsg[BR_ERR_DRIVE_UNKNOW]);

		// Test d'écriture sur le lecteur
		/////////////////////////////////
      aFullFile = IncludeTrailingBackslash(aDir + aRepTest);
		if(!FileExists(aFullFile) && !CreateDir(aFullFile))
         throw EAbort( aBRErrMsg[BR_ERR_DRIVE_PROTECT] );

		// Test de suppression du repertoire
		////////////////////////////////////
		if( RemoveDir( aFullFile ))
			return( BR_OK );
		}
	catch( Exception &e )
		{
		return( (BR_CODE)GetCodeErr(e.Message) );
		}

	return( BR_ERR_DRIVE_PROTECT );
	}

////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
AnsiString __fastcall CBackupRestore::MakeFullFile(const AnsiString &Path,const AnsiString &File )
	{
	AnsiString 	Sep = "\\";
	AnsiString	aTemp;
	AnsiString	aTemp2;
	int 		iPosSep;

	if( Path.c_str()[ Path.Length() - 1 ] == '\\' )
		aTemp = Path + File;
	else
		aTemp = Path + Sep + File;

	// Recherche d'un fichier de type racine ex: a:\file.dat => il faut virer le '\'
	aTemp2 = aTemp.SubString((iPosSep=aTemp.Pos(Sep)) + 1, aTemp.Length());
	if( aTemp2.Pos(Sep) == 0 )
		aTemp.Delete(iPosSep, 1);

	return( aTemp );
	}







////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
BR_CODE __fastcall CBackupRestore::BRImplodeFile()
	{
	TWriteParams  WrtParams;
	char         *pBuffer;
	unsigned int  nType = CMP_BINARY;
#ifdef ANCIEN_BR
	unsigned int  nSize = 2048;
#else
	unsigned int  nSize = 4096;
#endif

	pBuffer = new char[CMP_BUFFER_SIZE];

	WrtParams.nImplodeSize = 0;
	WrtParams.pWStream     = FCmpDst;
	WrtParams.pRStream     = FCmpSrc;

	implode(_ReadFile_, _WriteFile_, pBuffer, &WrtParams, &nType, &nSize);

	delete []pBuffer;
	lCmpDstSize = WrtParams.nImplodeSize;
//  lCmpDstSize = lCmpSrcSize;
	return BR_OK;
	}





/////////////////////////
/////////////////////////
////
////   Decompression
////
/////////////////////////
/////////////////////////
BR_CODE __fastcall CBackupRestore::BRExplodeFile( TFileStream *FDst)
	{
	TWriteParams  ReadParams;
	char         *pBuffer = new char[CMP_BUFFER_SIZE];

	ReadParams.pWStream   = FCmpDst;
	ReadParams.pRStream   = FDst;

	explode(_ReadFile_, _WriteFile_, pBuffer, &ReadParams);

	delete []pBuffer;
	return BR_OK;
	}                       


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::OnOwnPercents( 	TObject 			*Sender,
												Word 	    		BRPercents,
												Word 	    		PatternPercents,
												Word     			FilePercents,
												bool			 	Backup )
	{
	BarProgress->PBarPath->Position = PatternPercents;
	BarProgress->PBarFile->Position = FilePercents;
	}



////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                           BR_ON_INSERT_FLOPPY                              //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::OnOwnInsertFloppy( 	TObject 		   	*Sender,
													int 				NumDisk,
													const AnsiString &FilePath,
													bool 	  			&Abort,
													bool 	  			Backup )
	{
	char 	szTmp[ 44 ] = "";
	char 	Titre[ 20 ] = "";
	int	 	OldDrive 	= getdisk();
	bool	bAuto 		= false;

	strcpy( Titre, "Insertion disquette" );
	sprintf( szTmp, "Insérer la disquette N° %d", NumDisk );

	if( bAuto )
		{
		setdisk(0);
		if( getdisk() == 0 )
			Abort = false;
		else
			{
			if( MessageBox( 0, szTmp, Titre, MB_OKCANCEL ) == ID_CANCEL )
				Abort = true;
			else
				Abort = false;
			}
		setdisk( OldDrive );
		}
	else
		{
		if( MessageBox( 0, szTmp, Titre, MB_OKCANCEL ) == ID_CANCEL )
			Abort = true;
		else
			Abort = false;
		}
	}


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::OnOwnGetPatternToBackup(	TObject 			*Sender,
															Word  				MaxSizeUserDesc,
															Word 				&SizeUserDesc,
															void	 			*pvUserDesc,
															AnsiString     		&PathPattern,
															bool           		&Abort )
	{
	if( IemIndexListPathToBackup < ListPathToBackup->Count )
		{
		PathPattern = ListPathToBackup->Strings[IemIndexListPathToBackup];
		IemIndexListPathToBackup ++;
		Abort 			= false;
		}
	else
		Abort 			= true;
	}


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::OnOwnError( 	TObject 			*Sender,
												BR_CODE 	    	NumError,
												const AnsiString	&Msg,
												bool				Backup )
	{
	MessageBox( 0, Msg.c_str(), "Erreur", MB_ICONERROR );
	}


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::OnOwnHardError(	TObject 			*Sender,
												BR_CODE				NumError,
												const AnsiString	&Msg,
												bool				&Abort,
												bool  				Backup )
	{
	MessageBox( 0, Msg.c_str(), "Erreur", MB_ICONERROR );
	}


////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
void __fastcall CBackupRestore::OnOwnEnd(	TObject 			*Sender,
											BR_CODE				CodeRet,
											const AnsiString 	&Msg,
											bool 				Backup )
	{
	if( Backup )
		MessageBox( 0, Msg.c_str(), "Résultat de la sauvegarde", MB_ICONEXCLAMATION );
	else
		MessageBox( 0, Msg.c_str(), "Résultat de la restauration", MB_ICONEXCLAMATION );
	}




////////////////////////////////////////////////////////////////////////////////
//                                                                            //
//                                                                            //
//                                                                            //
////////////////////////////////////////////////////////////////////////////////
__fastcall CBackupRestore::~CBackupRestore()
	{
	BREnd(); // Destruction IOBuffer
    delete FBackup;
  	delete FCmpDst;
	delete FCmpSrc;
	}

namespace Cbackupr
	{
	void __fastcall PACKAGE Register()
		{
		TComponentClass classes[1] = {__classid(CBackupRestore)};
		RegisterComponents("EIC Outils", classes, 0);
		}
	}


